package com.sduept.nwld.dataserver.controller.equipment.assessment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.primefaces.PrimeFaces;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;

import com.sduept.bigdata.equipment.assessment.model.inspection.InspectionExpert;
import com.sduept.bigdata.equipment.assessment.service.InspectionExpertService;
import com.sduept.bigdata.equipment.assessment.service.InspectionStationService;
import com.sduept.bigdata.web.jsf.controller.AbstractController;
import com.sduept.nwld.dataserver.util.LibTreeNode;
import com.sduept.permission.entity.DepartmentEntityBean;
import com.sduept.permission.manager.DepartManager;
import com.sduept.utils.PingYinUtil;



/**
 * 专家选择器-controller
 * 
 *@author xuqinwen
 */
@Named
@ViewScoped
public class ExpertSelectorController extends AbstractController {
	@Autowired
	private DepartManager dm;
	@Autowired
	private InspectionExpertService expertService ;
	@Autowired
	private InspectionStationService stationService;
	/**
	 * 
	 */
	private static final long serialVersionUID = 6967192575583328458L;
	
	private TreeNode[] selectedNodes;
	/**
	 * 专家树 root -专家人员树
	 */
	private TreeNode expertRoot;
	/**
	 * 所传的experts数组
	 */
	private String[] experts ;
	/**
	 *  放专家首字母-全名
	 */
	private Map<String, List<String>> expertNameMap = new HashMap<>(); 
	/**
	 * 全部专家
	 */
	private List<InspectionExpert> expertList = new ArrayList<InspectionExpert>();
	/**
	 * 专家查询框的value
	 */
	private String expertName;
	/**
	 * 判断是否继续选择的状态
	 */
	private boolean choiceStatus ;
	/**
	 * 用于存放继续选择的专家人员code
	 */
	private Set<String> choiceExpertCodes = new HashSet<String>();
	private List<DepartmentEntityBean> deptRoots ;//根部门
	private Map<String,List<InspectionExpert>> deptExpertMap = new HashMap<String, List<InspectionExpert>>();//部门--专家 map 
	@PostConstruct
	public void init() {
		experts = getParameters("experts");
		expertList = expertService.findAll();
		deptRoots = dm.findRootDepts();
		initChoiceExpert();
		initDeptExpertMap();
		initExpertTree();
		initExpertNameMap();
	}
	
	
	private void initChoiceExpert() {
		if(experts!=null) {
			Set<String> codes = Stream.of(experts).collect(Collectors.toSet());
			choiceExpertCodes.addAll(codes);
		}
	}
	
	
	private void initDeptExpertMap() {//初始化部门-专家 map
		List<InspectionExpert>  allExperts   = expertService.findAll();;
		for (InspectionExpert expert : allExperts  ) {
		      String deptName = expert.getDeptName();
		      if(StringUtils.isBlank(deptName) ) {
		    	  deptName = deptRoots.get(0).getName();
		       }
		     List<InspectionExpert> values =  deptExpertMap.get(deptName);
			   if(values==null) {
				 values = new ArrayList<InspectionExpert>();
				deptExpertMap.put(deptName, values);
			  }
			 values.add(expert);
		 }
	}

	/**
	 * 获得专家姓名拼音-姓名   map
	 * @param personnels
	 * @return
	 */
	private void initExpertNameMap() {
		for (InspectionExpert expert : expertList) {
			String key  = PingYinUtil.getPingYinHeader(expert.getName());
			List<String> value =expertNameMap.get(key);
			if(value==null) {
				value = new ArrayList<String>();
				expertNameMap.put(key, value);
			}
			value.add(expert.getName());
		}
	}
	private void initExpertTree() {
		expertRoot = new LibTreeNode("Root", null);
		List<InspectionExpert> nullDeptName = getNullDeptExperts();
		List<DepartmentEntityBean> roots = dm.findRootDepts();
		for (DepartmentEntityBean s : roots) {
			TreeNode orgRoot = new LibTreeNode("dept", s, expertRoot);
			//递归root根下面的部门
			recursionExpertDept(s,orgRoot,choiceExpertCodes);
			for (InspectionExpert p : nullDeptName) {
				 DefaultTreeNode node = new DefaultTreeNode("expert", p, orgRoot);
				if(choiceExpertCodes.size()>0 && choiceExpertCodes.contains(p.getCode())) {
					node.setSelected(true);
				}
			}
			orgRoot.setExpanded(true);
		} 
	}
	private void recursionExpertDept(DepartmentEntityBean s, TreeNode orgRoot, Set<String> code) {
		List<DepartmentEntityBean> ds = dm.getDepartmentsByParent(s.getId()); 
		for (DepartmentEntityBean d : ds) {
			List<InspectionExpert> experts = expertService.findByDeptName(d.getName());
			if(experts.size()>0) {
				TreeNode treeNode = new LibTreeNode("dept", d, orgRoot);
				for (InspectionExpert p : experts) {
					 DefaultTreeNode node = new DefaultTreeNode("expert", p, treeNode);
					 if(code.size()>0 && code.contains(p.getCode())) {
							node.setSelected(true);
							parentSetExpanded(node);
							node.getParent().setExpanded(true);
						}
				}
			}
		}
	}
	private void parentSetExpanded(DefaultTreeNode node) {
            if(node.getParent()!=null) {
            	node.getParent().setExpanded(true);
                TreeNode treeNode =	node.getParent();
                parentSetExpanded((DefaultTreeNode) treeNode);
            }
	}

	private void recursionDept(List<DepartmentEntityBean> depts, Set<InspectionExpert> selects) {
		 for (DepartmentEntityBean departmentEntityBean : depts) {
			 List<DepartmentEntityBean> ds = dm.findAllDepartMentByParent(departmentEntityBean.getId());
				recursionDept(ds,selects);
				List<InspectionExpert> experts = expertService.findByDeptName(departmentEntityBean.getName());
				selects.addAll(experts);
		}
	}

	public void selectStandards() {
		List<InspectionExpert> selects = new ArrayList<InspectionExpert>();
		for (String code : choiceExpertCodes) {
			InspectionExpert expert = expertService.findByCode(code);
			selects.add(expert);
		}
		PrimeFaces.current().dialog().closeDynamic(selects);
	}
	
	
	 /**
     * 专家查询框展开所有专家
     * @param query
     * @return
     */
    public List<String> completeExperts(String query) {
    	List<String>  experts = new ArrayList<String>();
    	for (String s : expertNameMap.keySet()) {
			if(s.startsWith(query)) {
				experts.addAll(expertNameMap.get(s));
			}
		}
       return experts;	
    }
	
    /**
     * 专家树查人
     * @param event
     */
    public  void autoCompleteExpertTree(SelectEvent event) {
    	Object item = event.getObject();
		if (null != item) {
			filterTree(item.toString());
		}
		choiceStatus = true;
    }
	
    /**
     * 根据查询内容重新展示专家树
     * @param name
     */
	private void filterTree(String name) {
		InspectionExpert selectExpert = new  InspectionExpert();
			for (InspectionExpert expert : expertList) {
				if(expert.getName().equals(name)) {
					selectExpert=expert;
					break;
				}
			}
			//递归查询父部门 直到父部门为根部门  
			expertRoot = new LibTreeNode("Root", null);
			String rootName = deptRoots.get(0).getName();
			TreeNode orgRoot = new LibTreeNode("dept", rootName, expertRoot);
			orgRoot.setExpanded(true);
			String deptName = selectExpert.getDeptName();
			if(!StringUtils.isBlank(deptName)) {
				TreeNode childRoot = new LibTreeNode("dept", selectExpert.getDeptName(), orgRoot);
				childRoot.setExpanded(true);
				 new DefaultTreeNode("expert", selectExpert, childRoot);
			}else {
				new DefaultTreeNode("expert", selectExpert, orgRoot);
			}
	}

	/**
	 * 继续选择 
	 */
	public void addChoice() {
		choiceStatus = false;
		expertName = null;
		initExpertTreeByChoice();
	}
	
	private List<InspectionExpert> getNullDeptExperts() {
		List<InspectionExpert> nullDeptName = new ArrayList<InspectionExpert>();
		for (InspectionExpert e : expertList) {
			if(StringUtils.isBlank(e.getDeptName())) {
				nullDeptName.add(e);
			}
		}
		return nullDeptName;
	}
	
	private void initExpertTreeByChoice() {
		Set<String> code = choiceExpertCodes;
		expertRoot = new LibTreeNode("Root", null);
		List<InspectionExpert> nullDeptName = getNullDeptExperts();
		for (DepartmentEntityBean s : deptRoots) {
			TreeNode orgRoot = new LibTreeNode("dept", s, expertRoot);
			//递归root根下面的部门
			recursionExpertDept(s,orgRoot,code);
			List<InspectionExpert> experts = expertService.findByDeptName(s.getName());
			experts.addAll(nullDeptName);
			for (InspectionExpert p : experts) {
				 DefaultTreeNode node = new DefaultTreeNode("expert", p, orgRoot);
				if(code.size()>0 && code.contains(p.getCode())) {
					node.setSelected(true);
				}
			}
			orgRoot.setExpanded(true);
		}
	}
	
	
	/**
	 * 重置查询框
	 */
	public void refresh() {
		expertName = "";
		choiceStatus = false;
		choiceExpertCodes.clear();
		initExpertTree();
	}
	
	
   public void unSelect(NodeUnselectEvent event) {
	   if(choiceStatus==true) {
		   //此时是查询以后的选择事件
		   InspectionExpert expert = expertService.findByName(expertName);
		   choiceExpertCodes.remove(expert.getCode());
	   }else {
		   TreeNode node = event.getTreeNode();
		   Set<InspectionExpert> selects = new HashSet<InspectionExpert>();
		   List<String> codes = new ArrayList<String>();
		   if("dept".equals(node.getType())) {
			 //递归查子 直到getType不为dept  查人
			   getChildrenCheckBox(node,selects);
		   }else {
			   InspectionExpert expert = (InspectionExpert) node.getData();
			   choiceExpertCodes.remove(expert.getCode());
		   }
		   for (InspectionExpert inspectionExpert : selects) {
			   codes.add(inspectionExpert.getCode());
			}
		   choiceExpertCodes.removeAll(codes);
	   }
   }
  


     public void select(NodeSelectEvent event) {
	   TreeNode node = event.getTreeNode();
	   if(choiceStatus==true) {
		   InspectionExpert expert  = expertService.findByName(expertName);
			   choiceExpertCodes.add(expert.getCode());
	   }else {
		   Set<InspectionExpert> selects = new HashSet<InspectionExpert>();
		   if("dept".equals(node.getType())) { 
			 //递归查子 直到getType不为dept  查人
			   getChildrenCheckBox(node,selects);
		   }else {
			  InspectionExpert expert = (InspectionExpert) node.getData();
			   choiceExpertCodes.add(expert.getCode());
		   }
		   for (InspectionExpert inspectionExpert : selects) {
			   choiceExpertCodes.add(inspectionExpert.getCode());
			}
	   }
     }
   
   
	private void getChildrenCheckBox(TreeNode node, Set<InspectionExpert> selects) {
		for(TreeNode tn : node.getChildren()){
			if("dept".equals(tn.getType())) {
				List<DepartmentEntityBean> depts = dm.findAllDepartMentByParent(((DepartmentEntityBean)tn.getData()).getId());
				recursionDept(depts,selects);
				List<InspectionExpert> experts = expertService.findByDeptName(((DepartmentEntityBean)tn.getData()).getName());
				selects.addAll(experts);
			}else {
				InspectionExpert stand = (InspectionExpert) tn.getData();
				selects.add(stand);
			}
		}
     }

	/**
	 * 打开专家评价标准选择框
	 */
	public void openExpertSelectorDialog() {
		Map<String, Object> options = new HashMap<String, Object>();
		options.put("resizable", true);
		options.put("draggable", true);
		options.put("modal", true);
		options.put("width", 610);
		options.put("height", 700);
		Map<String, List<String>> params = new HashMap<>();
		PrimeFaces.current().dialog().openDynamic("/ui/common/expert_selector_multiple.xhtml",  options,params);
	}
	public TreeNode[] getSelectedNodes() {
		return selectedNodes;
	}
	public void setSelectedNodes(TreeNode[] selectedNodes) {
		this.selectedNodes = selectedNodes;
	}
	public TreeNode getExpertRoot() {
		return expertRoot;
	}
	public void setExpertRoot(TreeNode expertRoot) {
		this.expertRoot = expertRoot;
	}
	public String[] getExperts() {
		return experts;
	}
	public void setExperts(String[] experts) {
		this.experts = experts;
	}
	public String getExpertName() {
		return expertName;
	}
	public void setExpertName(String expertName) {
		this.expertName = expertName;
	}
	public boolean isChoiceStatus() {
		return choiceStatus;
	}
	public void setChoiceStatus(boolean choiceStatus) {
		this.choiceStatus = choiceStatus;
	}

	
}
